package ciphers;

import java.util.Arrays;
import java.util.Random;

public class Cipher {
	public static final char [] ALPHABET = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; 

	//ENCRYPTION
	public static String caesarCipher(int amt, String stringz1) { // works with spaces
		char [] newAlpha = new char[26]; 
		String stringz = stringz1.toLowerCase(); 

		for (int i=0; i<27; i++) {
			while (i + amt <= 25) {
				newAlpha[i+amt] = ALPHABET[i]; 
				i++;
			}
			if (i + amt > 25) {
				int x =0; 
				while (x<amt) {
					newAlpha[x] = ALPHABET[i]; 
					i++;
					x++; 
				}
			}
		} //works up to here :) Perfectly created newAlpha
		return printArray(stringz, newAlpha); 
	}
	public static String caesarianShift(int amt, String stringz) { // works with spaces
		String str1 = stringz.toLowerCase(); 
		String [] string = str1.split(" "); 
		String encryptedWord = ""; 

		//NEW PRINT METHOD
		for (String str : string) {
			for (int i=0; i<str.length(); i++) {
				int location = Arrays.binarySearch(ALPHABET, str.charAt(i)); 
				if (location + amt <= 25) {
					encryptedWord = encryptedWord + ALPHABET[location+amt]; 
				}
				else {
					encryptedWord = encryptedWord + ALPHABET[location + amt -26]; 
				}
			}
			encryptedWord = encryptedWord + " "; 
		}
		return encryptedWord; 
	}
	public static String ROT13(String str) { //copy of caesarianShift
		String encryptedWord = caesarianShift(13,str); 
		return encryptedWord; 
	}
	public static String keywordCipher(String key, String stringz) { //works with spaces
		char [] newAlpha = new char[26];  
		String keyword = removeDuplicates(key); 
		//		System.out.println("str: " + str); //DEBUG

		for (int i=0; i<keyword.length(); i++) {
			newAlpha[i] = keyword.charAt(i); 
			//	System.out.println(keyword.charAt(i) + " was added to newAlpha");  //DEBUG
		} //puts all of the keyword into new alphabet
		int x = keyword.length(); 
		for (int i=0; i<26; i++) {
			if (keyword.indexOf(ALPHABET[i]) == -1) {
				newAlpha[x] = ALPHABET[i]; 
				x++; 
				//			System.out.println(newAlpha[x-1] + " has been added to newAlpha "); //debug shit
			}
			//		else {  System.out.println("got into else loop "); } //more debug shit 
		} //works perfectly!

		//NEW PRINTING STRING METHOD
		return printArray(stringz, newAlpha); 
	}
	public static String substitutionCipher(String stringz) { //works with spaces
		char [] newAlpha = new char[26]; 

		for (int i=0; i<26; i++) {
			Random random = new Random();
			int tempIndex = random.nextInt(26); //too easy
			newAlpha[i] = ALPHABET[tempIndex]; 

		}

	/*	for (int i=0; i<26; i++) {
			System.out.println("index " + i + ": " + newAlpha[i]); 
		} */
		// works fine

		//NEW PRINTING STRING METHOD
		return printArray(stringz, newAlpha);  	 
	}

	//DECRYPTION
	public static String decryptCaesarShift(int amt, String stringz) { //works with spaces
		String str1 = stringz.toLowerCase(); 

		String[] string = str1.split(" "); 
		String decryptedWord = ""; 

		//NEW PRINT METHOD
		for (String str : string) {
			for (int i=0; i<str.length(); i++) {
				int location = Arrays.binarySearch(ALPHABET, str.charAt(i)); 
				if (location - amt<= 25 && location - amt > -1) {
					decryptedWord = decryptedWord + ALPHABET[location-amt]; 
				}
				else if ( location - amt <= -1) {
					int temp = location - amt; 
					decryptedWord = decryptedWord + ALPHABET[temp + 26]; 
				}
			}
			decryptedWord = decryptedWord + " "; 
		}

		return decryptedWord;
	}
	public static String decryptROT13(String str) { //copy of decryptCaesarShift
		String decryptedWord = decryptCaesarShift(13, str); 
		return decryptedWord; 
	}
	public static String decryptCaesarCipher(int amt, String stringz) { //works with spaces (utilizes printArrayCaesarDecipher)
		String str = stringz.toLowerCase(); 

		//making newAlpha based on switch amount
		char [] newAlpha = new char[26]; 

		for (int i=0; i<26; i++) {
			while (i + amt <= 25) {
				newAlpha[i+amt] = ALPHABET[i]; 
				i++;	}
			if (i + amt > 25) {
				int x =0; 
				while (x<amt) {
					newAlpha[x] = ALPHABET[i]; 
					i++;
					x++; } }  }

		return printAraryCaesarDecipher(str, newAlpha, amt); 
	}
	public static String decryptKeywordCipher(String key, String stringz) {
		char [] newAlpha = new char[26]; 
		String keyword = removeDuplicates(key); 

		for (int i=0; i<keyword.length(); i++) {
			newAlpha[i] = keyword.charAt(i); 		} 
		int x = keyword.length(); 
		for (int i=0; i<26; i++) {
			if (keyword.indexOf(ALPHABET[i]) == -1) {
				newAlpha[x] = ALPHABET[i]; 
				x++; }	}

		String decryptedWord = ""; 

		/*	for (int i=0; i<26;i++) {
			System.out.println("index " + i + ": " + newAlpha[i]); 
		} */
		String [] string = stringz.split(" "); 
		for (String str : string) {
			for (int i=0; i<str.length(); i++) {
				int index = linearSearch(newAlpha, str.charAt(i)); 
				decryptedWord = decryptedWord + ALPHABET[index]; 
				//	System.out.println("decrypted word: " + decryptedWord + " //// index: " + index); //DEBUG
			}
			decryptedWord = decryptedWord + " "; 
		}

		return decryptedWord; 
	}

	//EXTRA METHODS
	private static String removeDuplicates(String stringz) {
		String str = stringz.toLowerCase(); 
		String newString = ""; 
		for (int i=0; i<str.length(); i++) {
			char tempChar = str.charAt(i); 
			if (str.indexOf(tempChar) == str.lastIndexOf(tempChar)) { //if the first index of the char is equal to the last index (thus it is only there ONCE)
				newString = newString + tempChar; 
			}
			else if (newString.indexOf(tempChar) == -1) { //if newString does NOT contain the tempChar, ADD IT TO NEWSTRING
				newString = newString + tempChar; 
			}
			else {} //if newString DOES contain the tempChar, do NOTHING
		}
		return newString; 
	}
	private static int linearSearch(char[] arr, char key) {
		boolean found = false; 
		int i=0; 
		while (found == false && i<= 25) {
			for (i=0; i<arr.length; i++) {
				if (arr[i] == key) {
					found = true; 
					return i; 
				}
			}
		}
		return -1; 
	}
	@SuppressWarnings("unused")
	private static int linearSearch(int [] arr, int key) {
		boolean found = false; 
		int i=0; 
		while (found == false && i<= 25) {
			for (i=0; i<arr.length; i++) {
				if (arr[i] == key) {
					found = true; 
					return i; 
				}
			}
		}
		return -1; 
	}
	private static String printAraryCaesarDecipher(String words, char[] newAlpha, int amt) {
		String [] string = words.split(" "); 
		String decryptedWord = ""; 

		for (String str : string) {
			for (int i=0; i<str.length(); i++) {
				int location = Arrays.binarySearch(ALPHABET, str.charAt(i)); 
				int temp = location + amt; 

				if (temp <= 25 && temp >= 0) {
					decryptedWord = decryptedWord + ALPHABET[temp]; 
				}
				else if( temp > 25 )	{
					decryptedWord = decryptedWord + ALPHABET[temp - 26]; 
				}
			}
			decryptedWord = decryptedWord + " "; 
		}
		return decryptedWord; 
	}
	public static String printArray(String words, char [] newAlpha) {
		String [] string = words.split(" "); 

		String encryptedWord = ""; 

		//NEW PRINTING STRING METHOD
		for (String str : string) {
			for (int i=0; i<str.length(); i++) {
				int location = Arrays.binarySearch(ALPHABET, str.charAt(i)); 
				//	System.out.println("location: " + location); //DEBUG
				encryptedWord = encryptedWord + newAlpha[location]; 
			}
			encryptedWord = encryptedWord + " "; 
			//		System.out.println("encryptedWord: " + encryptedWord); //DEBUG
		}
		return encryptedWord; 
	}

}
